package com.xinghen.security.feign;

import feign.Feign;
import feign.Logger;
import feign.RequestInterceptor;
import feign.codec.ErrorDecoder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.http.client.Netty4ClientHttpRequestFactory;
import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails;
import org.springframework.security.oauth2.common.AuthenticationScheme;

/**
 * @author xinghen
 * @ClassName: OAuth2FeignAutoConfiguration
 * @Package: com.xinghen.security.feign
 * @Description oauth2 feign auto configuration
 * @create 2018-04-17 10:44
 */
@Configuration
@EnableConfigurationProperties(Oauth2ClientProperties.class)
public class OAuth2FeignAutoConfiguration {

    private final Oauth2ClientProperties oauth2ClientProperties;

    @Autowired
    public OAuth2FeignAutoConfiguration(Oauth2ClientProperties oauth2ClientProperties) {
        this.oauth2ClientProperties = oauth2ClientProperties;
    }

    @Bean
    public ClientCredentialsResourceDetails resourceDetails() {
        ClientCredentialsResourceDetails resourceDetails = new ClientCredentialsResourceDetails();
        resourceDetails.setId(oauth2ClientProperties.getId());
        resourceDetails.setAccessTokenUri(oauth2ClientProperties.getAccessTokenUrl());
        resourceDetails.setClientId(oauth2ClientProperties.getClientId());
        resourceDetails.setClientSecret(oauth2ClientProperties.getClientSecret());
        resourceDetails.setAuthenticationScheme(AuthenticationScheme.valueOf(oauth2ClientProperties
                .getClientAuthenticationScheme()));
        return resourceDetails;
    }

    @Bean
    public OAuth2RestTemplate oAuth2RestTemplate() {
        OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(resourceDetails(), new DefaultOAuth2ClientContext());
        restTemplate.setRequestFactory(new Netty4ClientHttpRequestFactory());
        return restTemplate;
    }

    @Bean
    public RequestInterceptor oauth2FeignRequestInterceptor(OAuth2RestTemplate restTemplate) {
        return new OAuth2FeignRequestInterceptor(restTemplate);
    }

    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }

    @Bean
    @Scope("prototype")
    public Feign.Builder feignBuilder() {
        return Feign.builder();
    }

    @Bean
    public ErrorDecoder errorDecoder() {
        return new Oauth2FeignErrorInterceptor();
    }

}
